<html>
<head><meta charset="utf-8"><title>Generics duplication across crate boundaries · t-compiler · Zulip Chat Archive</title></head>
<h2>Stream: <a href="https://rust-lang.github.io/zulip_archive/stream/131828-t-compiler/index.html">t-compiler</a></h2>
<h3>Topic: <a href="https://rust-lang.github.io/zulip_archive/stream/131828-t-compiler/topic/Generics.20duplication.20across.20crate.20boundaries.html">Generics duplication across crate boundaries</a></h3>

<hr>

<base href="https://rust-lang.zulipchat.com">

<head><link href="https://rust-lang.github.io/zulip_archive/style.css" rel="stylesheet"></head>

<a name="216919461"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/131828-t-compiler/topic/Generics%20duplication%20across%20crate%20boundaries/near/216919461" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Arlie Davis <a href="https://rust-lang.github.io/zulip_archive/stream/131828-t-compiler/topic/Generics.20duplication.20across.20crate.20boundaries.html#216919461">(Nov 16 2020 at 19:28)</a>:</h4>
<p>I just noticed something, and I'd like to know whether this is intentional behavior or is accidental.</p>
<p>I was debugging rustc.exe (on Windows, but all of this repros on Linux, too), and I noticed that there was more than one symbol (function) that had the exact same signature. It was a generic function, <code>feature_err_issue</code>, although the specific function isn't important. I verified that the type arguments were the same (they were) and that I was looking at a non-inlined instance of the function. (There were also inlined copies of this function, but I'm ignore that for now.).</p>
<p>So I looked at the undecorated symbol names, which are:</p>
<div class="codehilite"><pre><span></span><code>_ZN13rustc_session5parse17feature_err_issue17h9fe8fee81990e8abE
_ZN13rustc_session5parse17feature_err_issue17hfb08b04cceac9a60E
_ZN13rustc_session5parse17feature_err_issue17h320ef2c1e4daeaeeE
_ZN13rustc_session5parse17feature_err_issue17he074cef53958c416E
</code></pre></div>
<p>The thing that keeps these symbols from being the same is that they have different SVH suffixes. I checked the actual function bodies, and they are identical (even down to register allocator choices), so it's not like there was some subtle difference in compiler settings in each of the dependent crates.</p>
<p>So it looks like <code>rustc_session::parse::feature_err_issue</code> is defined in <code>rustc_session</code>, and used in a variety of other crates. So during monomorphization, is the SVH of the crate which triggered the instantiation of the function the thing that is being used to tag this symbol, rather than the SVH of the crate that contains the definition of the symbol?</p>



<a name="216921095"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/131828-t-compiler/topic/Generics%20duplication%20across%20crate%20boundaries/near/216921095" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Arlie Davis <a href="https://rust-lang.github.io/zulip_archive/stream/131828-t-compiler/topic/Generics.20duplication.20across.20crate.20boundaries.html#216921095">(Nov 16 2020 at 19:42)</a>:</h4>
<p>I created a minimal repro (4 crates) and verified that the same thing happens for those crates. I checked optimized, LTO optimized, both have same behavior.</p>



<a name="216921803"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/131828-t-compiler/topic/Generics%20duplication%20across%20crate%20boundaries/near/216921803" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Jonas Schievink  [he/him] <a href="https://rust-lang.github.io/zulip_archive/stream/131828-t-compiler/topic/Generics.20duplication.20across.20crate.20boundaries.html#216921803">(Nov 16 2020 at 19:49)</a>:</h4>
<p>I think this is intentional. You can try building with <code>-Zshare-generics=on</code>.</p>



<a name="216922263"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/131828-t-compiler/topic/Generics%20duplication%20across%20crate%20boundaries/near/216922263" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Arlie Davis <a href="https://rust-lang.github.io/zulip_archive/stream/131828-t-compiler/topic/Generics.20duplication.20across.20crate.20boundaries.html#216922263">(Nov 16 2020 at 19:53)</a>:</h4>
<p>Ok. Why would we ever not want to share generics?</p>



<a name="216922422"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/131828-t-compiler/topic/Generics%20duplication%20across%20crate%20boundaries/near/216922422" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Jonas Schievink  [he/him] <a href="https://rust-lang.github.io/zulip_archive/stream/131828-t-compiler/topic/Generics.20duplication.20across.20crate.20boundaries.html#216922422">(Nov 16 2020 at 19:54)</a>:</h4>
<p>It produces code that is quite a lot slower</p>



<a name="216922451"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/131828-t-compiler/topic/Generics%20duplication%20across%20crate%20boundaries/near/216922451" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Jonas Schievink  [he/him] <a href="https://rust-lang.github.io/zulip_archive/stream/131828-t-compiler/topic/Generics.20duplication.20across.20crate.20boundaries.html#216922451">(Nov 16 2020 at 19:54)</a>:</h4>
<p>Because inlining becomes impossible without LTO</p>



<a name="216922620"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/131828-t-compiler/topic/Generics%20duplication%20across%20crate%20boundaries/near/216922620" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Arlie Davis <a href="https://rust-lang.github.io/zulip_archive/stream/131828-t-compiler/topic/Generics.20duplication.20across.20crate.20boundaries.html#216922620">(Nov 16 2020 at 19:55)</a>:</h4>
<p>In this case, though, the compiler has already decided not to inline a function. So there's going to be a non-inlined function body. I'm curious why we wouldn't want COMDAT-folding (or similar techniques on other platforms) to combine these into a single function body, at link time.</p>



<a name="216922692"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/131828-t-compiler/topic/Generics%20duplication%20across%20crate%20boundaries/near/216922692" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Arlie Davis <a href="https://rust-lang.github.io/zulip_archive/stream/131828-t-compiler/topic/Generics.20duplication.20across.20crate.20boundaries.html#216922692">(Nov 16 2020 at 19:56)</a>:</h4>
<p>This seems orthogonal to the decision of whether or not to inline a generic function.</p>



<a name="216923383"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/131828-t-compiler/topic/Generics%20duplication%20across%20crate%20boundaries/near/216923383" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Arlie Davis <a href="https://rust-lang.github.io/zulip_archive/stream/131828-t-compiler/topic/Generics.20duplication.20across.20crate.20boundaries.html#216923383">(Nov 16 2020 at 20:01)</a>:</h4>
<p>Why not build things as they are now, but use the SVH suffix of the crate that defines the generic function, rather than the crates that trigger its instantiation, and mark the generated function as "multiple defs are OK, use any"?</p>



<a name="216980253"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/131828-t-compiler/topic/Generics%20duplication%20across%20crate%20boundaries/near/216980253" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> bjorn3 <a href="https://rust-lang.github.io/zulip_archive/stream/131828-t-compiler/topic/Generics.20duplication.20across.20crate.20boundaries.html#216980253">(Nov 17 2020 at 09:17)</a>:</h4>
<p><span class="user-mention silent" data-user-id="274471">Arlie Davis</span> <a href="#narrow/stream/131828-t-compiler/topic/Generics.20duplication.20across.20crate.20boundaries/near/216922620">said</a>:</p>
<blockquote>
<p>In this case, though, the compiler has already decided not to inline a function.</p>
</blockquote>
<p>It hasn't at when deciding the codegen unit partitioning. It is LLVM that decides this after all mono items have be translated into LLVM-ir.<br>
<span class="user-mention silent" data-user-id="274471">Arlie Davis</span> <a href="#narrow/stream/131828-t-compiler/topic/Generics.20duplication.20across.20crate.20boundaries/near/216922620">said</a>:</p>
<blockquote>
<p>I'm curious why we wouldn't want COMDAT-folding (or similar techniques on other platforms) to combine these into a single function body, at link time.</p>
</blockquote>
<p>This used to be used by rustc, but it was changed. I don't quite remember why, but it may be related to linker problems. (maybe it got much slower?) Also COMDAT-folding inhibits certain optimizations around atomics. LLVM may decide to strengthen the atomic orderings of same function in different incompatible ways in different codegen units depending on which functions call them. Also LLVM may decide that all functions that could call a certain function use the same constant as an argument and replace that argument with the constant <strong>without</strong> inlining. If this constant happens to be different in different codegen units, that would be a problem. For this reason COMDAT-folding prevents this optimization.</p>
<p><span class="user-mention silent" data-user-id="274471">Arlie Davis</span> <a href="#narrow/stream/131828-t-compiler/topic/Generics.20duplication.20across.20crate.20boundaries/near/216923383">said</a>:</p>
<blockquote>
<p>Why not build things as they are now, but use the SVH suffix of the crate that defines the generic function, rather than the crates that trigger its instantiation</p>
</blockquote>
<p>It already does this as far as I know, but <code>feature_err_issue</code> has a generic parameter <code>span: impl Into&lt;MultiSpan&gt;</code> which probably gets passed different types.</p>



<a name="217187792"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/131828-t-compiler/topic/Generics%20duplication%20across%20crate%20boundaries/near/217187792" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Arlie Davis <a href="https://rust-lang.github.io/zulip_archive/stream/131828-t-compiler/topic/Generics.20duplication.20across.20crate.20boundaries.html#217187792">(Nov 18 2020 at 19:52)</a>:</h4>
<p><span class="user-mention" data-user-id="133247">@bjorn3</span> , thanks for the background on this. I know it's a complex topic, so I'm asking to learn, not to impugn any decisions that have been made.</p>
<blockquote>
<p>It already does this as far as I know, but feature_err_issue has a generic parameter span: impl Into&lt;MultiSpan&gt; which probably gets passed different types.</p>
</blockquote>
<p>In this case, I'm certain that there are duplicates, even for the same generic type args. That's what prompted me to start this thread.</p>



<a name="217241352"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/131828-t-compiler/topic/Generics%20duplication%20across%20crate%20boundaries/near/217241352" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> bjorn3 <a href="https://rust-lang.github.io/zulip_archive/stream/131828-t-compiler/topic/Generics.20duplication.20across.20crate.20boundaries.html#217241352">(Nov 19 2020 at 08:43)</a>:</h4>
<p>If you use <code>-Zsymbol-mangling-version=v0</code>, the generic parameters should be encoded.</p>



<hr><p>Last updated: Aug 07 2021 at 22:04 UTC</p>
</html>